`include "mycpu.h"
`include "tools.v"

module ID_stage(
    input                          clk           ,
    input                          reset         ,
    //allowin
    input                          es_allowin    ,
    output                         ds_allowin    ,
    //from fs
    input                          fs_to_ds_valid,
    input  [`FS_TO_DS_BUS_WD -1:0] fs_to_ds_bus  ,//64
    input [`BPU_TO_DS_BUS_WD -1:0] bpu_to_ds_bus ,
    //to es
    output                         ds_to_es_valid,
    output [`DS_TO_ES_BUS_WD -1:0] ds_to_es_bus  ,//136
    //to fs
    output [`BR_BUS_WD       -1:0] br_bus        ,//32
    output [`DS_TO_BPU_BUS_WD -1:0] ds_to_bpu_bus,
    //to rf: for write back
    input  [`WS_TO_RF_BUS_WD -1:0] ws_to_rf_bus  , //38
    output [`DS_TO_TH_BUS_WD  -1:0] ds_to_th_bus ,
    input  [`ES_TO_DS_BUS_WD  -1:0] es_to_ds_bus ,
    input  [`_TO_DS_BUS_WD  -1:0] ms_to_ds_bus ,
    input  [`_TO_DS_BUS_WD  -1:0] ws_to_ds_bus ,
    input                         cr_flush_o,
    //time_int//
    input                           time_int,
    input                           csr_MTIE,
    input                           csr_MIE,
    // input  [17:0]                 cr_to_ds_bus,
    input  [`_OUT_TH_BUS_WD   -1:0] data_haza_bus, //冲突�?测单元返回的信号
    output wire [`REG_BUS] regs_o[ 31 :0]
);


//RV64I与mips32
//译码：同为32位指令码，但不同的位置有着不同的意义
//跳转：由于少了转移延迟槽，跳转基于的PC有可能会不同，立即数译码不一样了
//PC；32bits => 64bits
//寄存器堆：32bits*32 => 64bits*32
//寄存器堆：取消寄存器写使能，采用一位寄存器写使能
//前递：前递数据变成64bits，取消寄存器字节写使能，全变成一位的写使能

reg                          ds_valid;
reg                          inst_jump_reg;
reg  [`FS_TO_DS_BUS_WD -1:0] fs_to_ds_bus_r;
wire                         ds_ready_go;
wire                         fs_to_ds_ex;



wire                         rf_we;
wire [ 4                 :0] rf_waddr;
wire [63                 :0] fs_pc;
// (*mark_debug = "true"*) wire [31                 :0] ds_inst;
wire [31:0] ds_inst;
// (*mark_debug = "true"*) wire [31                 :0] ds_pc  ;
wire [63:0] ds_pc;
wire [63                 :0] rf_wdata;
wire [63                 :0] br_target;
wire [15:0] alu_op;

// wire        hi_lo_to_com;
wire        rs_eq_rt;
wire        data_haza;
wire        ds_br_stall;  
wire        com_to_hi_lo;
wire        hi_lo_wen;
wire        br_inst;
wire        br_taken;
wire        load_op;
wire        src2_is_sa;

wire [63:0] ds_bpu_pc;
wire [63:0] real_npc;

wire        src1_is_pc;
wire        src2_is_imm;
wire        src2_is_imm_0;
wire        src2_is_8;
wire        res_from_mem;
wire        gr_we;
wire        inst_jump;
wire        ds_bd;
wire        ds_ri;
wire        mem_we;
wire  inst_lui    ;
wire  inst_auipc  ;
wire  inst_jal    ;
wire  inst_jalr   ;
wire  inst_beq    ;
wire  inst_bne    ;
wire  inst_blt    ;
wire  inst_bge    ;
wire  inst_bltu   ;
wire  inst_bgeu   ;
wire  inst_lb     ;
wire  inst_lh     ;
wire  inst_lw     ;
wire  inst_lbu    ;
wire  inst_lhu    ;
wire  inst_sb     ;
wire  inst_sh     ;
wire  inst_sw     ;
wire  inst_addi   ;
wire  inst_slti   ;
wire  inst_sltiu  ;
wire  inst_xori   ;
wire  inst_ori    ;
wire  inst_andi   ;
wire  inst_slli   ;
wire  inst_srli   ;
wire  inst_srai   ;
wire  inst_add    ;
wire  inst_sub    ;
wire  inst_sll    ;
wire  inst_slt    ;
wire  inst_sltu   ;
wire  inst_xor    ;
wire  inst_srl    ;
wire  inst_sra    ;
wire  inst_or     ;
wire  inst_and    ;
wire  inst_fence  ;
wire  inst_ecall  ;
wire  inst_ebreak ;
//RV64I//
wire  inst_lwu;
wire  inst_ld;
wire  inst_sd;
wire  inst_rv64_slli;
wire  inst_rv64_srli;
wire  inst_rv64_srai;
wire  inst_addiw;
wire  inst_slliw;
wire  inst_srliw;
wire  inst_sraiw;
wire  inst_addw;
wire  inst_subw;
wire  inst_sllw;
wire  inst_srlw;
wire  inst_sraw;
//csr
wire  inst_csrrw ; 
wire  inst_csrrs ;
wire  inst_csrrc ;
wire  inst_csrrwi;
wire  inst_csrrsi;
wire  inst_csrrci;
wire  inst_mret;

wire[11:0] csr_addr;
wire[4:0] zimm;
wire        ds_int;
wire        ds_ex;

assign ds_ex = ds_int || inst_ecall;





wire        inst_mfc0;
assign inst_mfc0 = 1'b0;

wire        src2_rv64_sa;
wire        src2_rv32_sa;
wire        es_load_op;
wire        ms_valid;
wire        es_valid;
wire        ws_valid;
wire        ds_can_ov;   
wire        c0_status_ie;
wire        c0_status_exl;
wire        ds_bp;
wire        ds_sys;
wire        f_fs_adel;
wire        es_gr_we;
wire        ms_gr_we;
wire        ws_gr_we;
wire [ 4:0] rf_raddr1;
wire [ 4:0] rf_raddr2;
wire [ 4:0] dest;
wire [ 4:0] rs;
wire [ 4:0] rt;
wire [ 4:0] rd;
wire [ 4:0] sa;
wire [ 3:0] mem_op;
wire [4:0 ] es_dest;
wire [4:0 ] ms_dest;
wire [4:0 ] ws_dest;
wire [ 6:0] op;
wire [6:0 ] load_op_clear;
wire [63:0] rs_value;
wire [63:0] rt_value;

wire [31:0] I_imm;
wire [31:0] S_imm;
wire [31:0] B_imm;
wire [31:0] U_imm;
wire [31:0] J_imm;
wire [31:0] imm;
wire is_J_imm;
wire is_I_imm;
wire is_B_imm;
wire is_S_imm;
wire is_U_imm;

wire [63:0] rf_rdata1;
wire [63:0] rf_rdata2;
wire [63:0] es_fw_data;
wire [63:0] ms_fw_data;
wire [63:0] ws_fw_data;
wire [63:0] next_pc;
wire [128:0] op_d;
wire [63:0] func_d;

wire [63:0] add_src1;
wire [63:0] add_src2;
wire src2_is_4;
///////FOR_BPU////
wire [63:0] x1_value;
wire [63:0] xn_value;
wire [4:0]  rxn;
wire        ds_may_wait;
wire        need_rs2;
wire        inst_0x7b;

assign inst_0x7b = ds_inst[6:0] == 7'h7B;
assign rxn = bpu_to_ds_bus;
assign ds_to_bpu_bus = {ds_may_wait,xn_value,x1_value};
assign need_rs2 =
|  inst_beq    |  inst_bne    |  inst_blt    |  inst_bge    |  inst_bltu   
|  inst_bgeu   |  inst_sb     |  inst_sh     |  inst_sw     |  inst_add    
|  inst_sub    |  inst_sll    |  inst_slt    |  inst_sltu   |  inst_xor    
|  inst_srl    |  inst_sra    |  inst_or     |  inst_and    |  inst_sd
|  inst_addw   |  inst_subw|  inst_sllw|  inst_srlw|  inst_sraw;

assign ds_may_wait = ds_valid && need_rs2 
                  || es_valid && rxn == es_dest && es_gr_we
                  || ms_valid && rxn == ms_dest && ms_gr_we
                  || ws_valid && rxn == ws_dest && ws_gr_we; 

assign {rf_we   ,  //69:69
        rf_waddr,  //68:64
        rf_wdata   //63:0
       } = ws_to_rf_bus;

assign {ds_br_stall,data_haza}  = data_haza_bus;
assign {fs_to_ds_ex,
        ds_inst,
        ds_bpu_pc,
        ds_pc  } = fs_to_ds_bus_r;

assign fs_pc = fs_to_ds_bus[63:0];
assign f_fs_adel = fs_to_ds_ex;
assign ds_sys = 1'b0;
assign ds_bp =  1'b0;


assign ds_ri  = 
~inst_lui     & ~inst_auipc   & ~inst_jal     & ~inst_jalr    & 
~inst_beq     & ~inst_bne     & ~inst_blt     & ~inst_bge     & ~inst_bltu    & ~inst_bgeu    & 
~inst_lb      & ~inst_lh      & ~inst_lw      & ~inst_lbu     & ~inst_lhu     & ~inst_sb      & 
~inst_sh      & ~inst_sw      & ~inst_addi    & ~inst_slti    & ~inst_sltiu   & ~inst_xori    & 
~inst_ori     & ~inst_andi    & ~inst_slli    & ~inst_srli    & ~inst_srai    & ~inst_add     & 
~inst_sub     & ~inst_sll     & ~inst_slt     & ~inst_sltu    & ~inst_xor     & ~inst_srl     & 
~inst_sra     & ~inst_or      & ~inst_and     & ~inst_fence   & ~inst_ecall   & ~inst_ebreak   ;

// assign  {c0_status_exl,c0_status_ie,c0_status_im,c0_cause_ip} = cr_to_ds_bus;

// assign ds_int = ((c0_cause_ip[7:0] & c0_status_im[7:0]) != 8'h00) && c0_status_ie ==1'b1 && c0_status_exl == 1'b0 ;
// assign ds_ex    = ds_ri || ds_bp || ds_int || ds_sys || f_fs_adel;
assign br_bus  = {ds_br_stall,br_taken,br_target};
assign ds_int  = time_int && csr_MTIE && csr_MIE;

assign ds_to_es_bus = {
                        ds_int,
                        ds_ex,
                        inst_mret,
                        inst_csrrw ,
                        inst_csrrs ,
                        inst_csrrc ,
                        inst_csrrwi,
                        inst_csrrsi,
                        inst_csrrci,                        
                        zimm,
                        csr_addr,
                        inst_0x7b, 
                        mem_op, //363:360
                        load_op_clear,//359:353
                        alu_op      ,  //352:337
                        load_op     ,  //336  //少了load_op造成后面�?系列的Z
                        src2_rv64_sa     ,//335
                        src2_rv32_sa     ,//334
                        src1_is_pc  ,  //333:333
                        src2_is_imm ,  //332:332
                        src2_is_4   ,  //331:331
                        gr_we       ,  //330:330
                        mem_we      ,  //229:229
                        dest        ,  //228:224
                        imm         ,  //223:129
                        rs_value    ,  //191 : 128
                        rt_value    ,  //127 :64
                        ds_inst     ,
                        ds_bpu_pc   ,
                        br_target   ,
                        ds_pc          //63 :0
                      };
    
assign ds_to_th_bus = { ds_ex,
                        inst_mfc0,
                        ds_valid , //11:11
                        br_inst,  //10:10
                        rt,//9:5
                        rs //4:0
                    };
assign ds_ready_go    =  ~data_haza  ;
assign ds_allowin     =  !ds_valid || ds_ready_go && es_allowin;//ds_vaild出现了X，最后发现ds_vaild没赋�?//Error_03
assign ds_to_es_valid = ds_valid && ds_ready_go;
always @(posedge clk) begin
    if (reset | cr_flush_o) begin
        ds_valid <= 1'b0;
    end
    else if (ds_allowin) begin
        ds_valid <= fs_to_ds_valid;
    end
    if (fs_to_ds_valid && ds_allowin) begin
        fs_to_ds_bus_r <= fs_to_ds_bus;
    end
end
wire [2:0] func3;
wire [7:0] func3_d;
wire [6:0] func7;
wire [127:0] func7_d;
wire [4:0]  rs1;
wire [4:0]  rs2;
wire [31:0] rs2_d;


assign is_J_imm = inst_jal;
assign is_S_imm = inst_sb   | inst_sw | inst_sh | inst_sd;
assign is_I_imm = inst_jalr | inst_lb | inst_lh | inst_lw | inst_lbu | inst_lhu 
                | inst_addi | inst_slti         | inst_sltiu         | inst_xori
                | inst_ori  | inst_andi         | inst_lwu           | inst_ld | inst_addiw
                | inst_slli |  inst_srli | inst_srai  | inst_slliw|  inst_srliw| inst_sraiw;
assign is_B_imm = inst_beq || inst_bne || inst_blt || inst_bge || inst_bltu || inst_bgeu;
assign is_U_imm = inst_lui | inst_auipc;

assign imm      = ({32{inst_jal}}   & J_imm)
                | ({32{is_I_imm}}   & I_imm)
                | ({32{is_B_imm}}   & B_imm)
                | ({32{is_S_imm}}   & S_imm)
                | ({32{is_U_imm}}   & U_imm);

assign I_imm = {{21{ds_inst[31]}},ds_inst[30:20]};
assign S_imm = {{21{ds_inst[31]}},ds_inst[30:25],ds_inst[11:7]};
assign B_imm = {{20{ds_inst[31]}},ds_inst[7],ds_inst[30:25],ds_inst[11:8],1'b0};
assign U_imm = {ds_inst[31:12],12'b0};
assign J_imm = {{12{ds_inst[31]}},ds_inst[19:12],ds_inst[20],ds_inst[30:21],1'b0};

assign op   = ds_inst[6:0];
assign rd   = ds_inst[11:7];
assign func3= ds_inst[14:12];
assign rs1  = ds_inst[19:15];
assign rs2  = ds_inst[24:20];
assign func7= ds_inst[31:25];
assign rs   = rs1;
assign rt   = rs2;
assign csr_addr = ds_inst[31:20];
assign zimm = rs1;


decoder_7_128 u_dec0(.in(op  ),     .out(op_d  ));
decoder_3_8   u_dec1(.in(func3),    .out(func3_d));
decoder_7_128 u_dec2(.in(func7  ),  .out(func7_d));
decoder_5_32  u_dec3(.in(rs2  ),    .out(rs2_d  ));
// decoder_5_32 u_dec4(.in(rd  ), .out(rd_d  ));
// decoder_5_32 u_dec5(.in(sa  ), .out(sa_d  ));

assign inst_lui     = op_d[7'h37];
assign inst_auipc   = op_d[7'h17];
assign inst_jal     = op_d[7'h6f];
assign inst_jalr    = op_d[7'h67] & func3_d[3'h0];
assign inst_beq     = op_d[7'h63] & func3_d[3'h0];
assign inst_bne     = op_d[7'h63] & func3_d[3'h1];
assign inst_blt     = op_d[7'h63] & func3_d[3'h4];
assign inst_bge     = op_d[7'h63] & func3_d[3'h5];
assign inst_bltu    = op_d[7'h63] & func3_d[3'h6];
assign inst_bgeu    = op_d[7'h63] & func3_d[3'h7];
assign inst_lb      = op_d[7'h03] & func3_d[3'h0];
assign inst_lh      = op_d[7'h03] & func3_d[3'h1];
assign inst_lw      = op_d[7'h03] & func3_d[3'h2];
assign inst_lbu     = op_d[7'h03] & func3_d[3'h4];
assign inst_lhu     = op_d[7'h03] & func3_d[3'h5];
assign inst_sb      = op_d[7'h23] & func3_d[3'h0];
assign inst_sh      = op_d[7'h23] & func3_d[3'h1];
assign inst_sw      = op_d[7'h23] & func3_d[3'h2];
assign inst_addi    = op_d[7'h13] & func3_d[3'h0];
assign inst_slti    = op_d[7'h13] & func3_d[3'h2];
assign inst_sltiu   = op_d[7'h13] & func3_d[3'h3];
assign inst_xori    = op_d[7'h13] & func3_d[3'h4];
assign inst_ori     = op_d[7'h13] & func3_d[3'h6];
assign inst_andi    = op_d[7'h13] & func3_d[3'h7];
// assign inst_slli    = op_d[7'h13] & func3_d[3'h1] & func7_d[7'h00];
// assign inst_srli    = op_d[7'h13] & func3_d[3'h5] & func7_d[7'h00];
// assign inst_srai    = op_d[7'h13] & func3_d[3'h5] & func7_d[7'h20];
assign inst_slli    = op_d[7'h13] & func3_d[3'h1] & ds_inst[31:26] == 6'h00;
assign inst_srli    = op_d[7'h13] & func3_d[3'h5] & ds_inst[31:26] == 6'h00;
assign inst_srai    = op_d[7'h13] & func3_d[3'h5] & ds_inst[31:26] == 6'h10;

assign inst_add     = op_d[7'h33] & func3_d[3'h0] & func7_d[7'h00];
assign inst_sub     = op_d[7'h33] & func3_d[3'h0] & func7_d[7'h20];
assign inst_sll     = op_d[7'h33] & func3_d[3'h1] & func7_d[7'h00];
assign inst_slt     = op_d[7'h33] & func3_d[3'h2] & func7_d[7'h00];
assign inst_sltu    = op_d[7'h33] & func3_d[3'h3] & func7_d[7'h00];
assign inst_xor     = op_d[7'h33] & func3_d[3'h4] & func7_d[7'h00];
assign inst_srl     = op_d[7'h33] & func3_d[3'h5] & func7_d[7'h00];
assign inst_sra     = op_d[7'h33] & func3_d[3'h5] & func7_d[7'h20];
assign inst_or      = op_d[7'h33] & func3_d[3'h6] & func7_d[7'h00];
assign inst_and     = op_d[7'h33] & func3_d[3'h7] & func7_d[7'h00];

assign inst_fence   = op_d[7'h0f] & func3_d[3'h0];
assign inst_ecall   = op_d[7'h73] & func3_d[3'h0] & func7_d[7'h00] & rs2_d[5'h00];
assign inst_ebreak  = op_d[7'h73] & func3_d[3'h0] & func7_d[7'h01] & rs2_d[5'h01];
//RV64I//
assign inst_lwu     = op_d[7'h03] & func3_d[3'h6];
assign inst_ld      = op_d[7'h03] & func3_d[3'h3];
assign inst_sd      = op_d[7'h23] & func3_d[3'h3];
assign inst_rv64_slli = op_d[7'h13] & func3_d[3'h1] & ds_inst[31:26] == 6'h00;
assign inst_rv64_srli = op_d[7'h13] & func3_d[3'h5] & ds_inst[31:26] == 6'h00;
assign inst_rv64_srai = op_d[7'h13] & func3_d[3'h5] & ds_inst[31:26] == 6'h10;
assign inst_addiw  = op_d[7'h1b] & func3_d[3'h0];
assign inst_slliw  = op_d[7'h1b] & func3_d[3'h1] & func7_d[7'h00];
assign inst_srliw  = op_d[7'h1b] & func3_d[3'h5] & func7_d[7'h00];
assign inst_sraiw  = op_d[7'h1b] & func3_d[3'h5] & func7_d[7'h20];
assign inst_addw   = op_d[7'h3b] & func3_d[3'h0] & func7_d[7'h00];
assign inst_subw   = op_d[7'h3b] & func3_d[3'h0] & func7_d[7'h20];
assign inst_sllw   = op_d[7'h3b] & func3_d[3'h1] & func7_d[7'h00];
assign inst_srlw   = op_d[7'h3b] & func3_d[3'h5] & func7_d[7'h00];
assign inst_sraw   = op_d[7'h3b] & func3_d[3'h5] & func7_d[7'h20];

////CSR////
assign inst_csrrw  = op_d[7'h73] & func3_d[3'h1];
assign inst_csrrs  = op_d[7'h73] & func3_d[3'h2];
assign inst_csrrc  = op_d[7'h73] & func3_d[3'h3];
assign inst_csrrwi = op_d[7'h73] & func3_d[3'h5];
assign inst_csrrsi = op_d[7'h73] & func3_d[3'h6];
assign inst_csrrci = op_d[7'h73] & func3_d[3'h7];
assign inst_mret   = op_d[7'h73] & func3_d[3'h0] & func7_d[7'h18];


assign alu_op[ 0] = inst_add | inst_addi| inst_lw | inst_sw | inst_jal | inst_jalr
                  | inst_lb  | inst_lbu   | inst_lh | inst_lhu | inst_sb | inst_sh 
                  | inst_lwu | inst_ld  | inst_sd | inst_addiw | inst_addw | inst_auipc  ;
assign alu_op[ 1] = inst_sub | inst_subw;
assign alu_op[ 2] = inst_slt  | inst_slti;
assign alu_op[ 3] = inst_sltiu| inst_sltu;
assign alu_op[ 4] = inst_and  | inst_andi;
assign alu_op[ 5] = 1'b0;//inst_nor  ;
assign alu_op[ 6] = inst_or   | inst_ori;
assign alu_op[ 7] = inst_xor | inst_xori;
assign alu_op[ 8] = inst_sll | inst_slliw | inst_sllw | inst_rv64_slli;
assign alu_op[ 9] = inst_srl | inst_srliw | inst_srlw | inst_rv64_srli;
assign alu_op[10] = inst_sra | inst_sraiw | inst_sraw | inst_rv64_srai;
assign alu_op[11] = inst_lui;
assign alu_op[12] = inst_addiw | inst_slliw| inst_srliw| inst_sraiw| inst_addw | inst_subw | inst_sllw | inst_srlw | inst_sraw ;    //inst_mult;
assign alu_op[13] = 1'b0;   //inst_multu;
assign alu_op[14] = 1'b0;   //inst_div;
assign alu_op[15] = 1'b0;   //inst_divu;

assign load_op_clear[ 0] = inst_lw;
assign load_op_clear[ 1] = inst_lb;
assign load_op_clear[ 2] = inst_lbu;
assign load_op_clear[ 3] = inst_lh;
assign load_op_clear[ 4] = inst_lhu;
assign load_op_clear[ 5] = inst_lwu;
assign load_op_clear[ 6] = inst_ld;
assign mem_op[ 0]        = inst_sw;
assign mem_op[ 1]        = inst_sh;
assign mem_op[ 2]        = inst_sb;
assign mem_op[ 3]        = inst_sd;


//Error_04
   //load_op//不是寄存器写使能，�?�是内存的写使能//es_res_from_mem
assign load_op      = inst_lw    | inst_lb  | inst_lbu  | inst_lh    |inst_lhu | inst_lwu | inst_ld;
assign src2_is_sa   = inst_sll | inst_slliw | inst_sllw | inst_rv64_slli | inst_srl | inst_srliw | inst_srlw | inst_rv64_srli 
                    | inst_sra | inst_sraiw | inst_sraw | inst_rv64_srai;

assign src1_is_pc   = inst_jal   | inst_jalr| inst_auipc;
assign src2_is_imm  = inst_addi | inst_slti | inst_sltiu |inst_lui |   |inst_xori | inst_ori | inst_andi  | inst_addiw 
                    | inst_lw   | inst_lb   | inst_lbu   | inst_lh | inst_lhu | inst_lwu | inst_ld
                    | inst_sw   | inst_sh   | inst_sb    | inst_sd | inst_auipc
                    | inst_slli |  inst_srli | inst_srai  | inst_slliw|  inst_srliw| inst_sraiw;
// assign src2_is_imm  = is_J_imm | is_S_imm | is_I_imm | is_B_imm | is_U_imm;
assign src2_is_imm_0=  1'b0  ;
assign src2_is_4    = inst_jal   | inst_jalr| inst_auipc ;

//hi,lo寄存器的写使�?
assign hi_lo_wen = 1'b0;//inst_mtlo    ||inst_mthi || inst_divu  || inst_div || inst_mult || inst_multu;
//jal也是有目的寄存器的，当时弄混了以为jal没有目的寄存�?
assign src2_rv64_sa      = inst_sll   | inst_srl | inst_sra;
assign src2_rv32_sa      = inst_slliw | inst_srliw | inst_sraiw ;

assign res_from_mem = inst_lw    | inst_lb  | inst_lbu  | inst_lh | inst_lhu | inst_lwu | inst_ld;
assign gr_we		= ~inst_sw  & ~inst_sh & ~inst_sb    & ~inst_beq  & ~inst_bne     &~inst_blt & ~inst_bge &~inst_bltu & ~inst_bgeu      
                    & ~inst_fence & ~inst_ecall & ~inst_ebreak & ~inst_sd & ~inst_0x7b & ~inst_mret;
                                                                                                                      
assign mem_we       = inst_sw| inst_sh       | inst_sb  | inst_sd;
assign br_inst     =    inst_beq | inst_bne | inst_blt | inst_bltu| inst_bge | inst_bgeu| inst_jalr| inst_jal;
assign dest         =  rd;
                                    
assign ds_can_ov    = inst_add | inst_addi | inst_sub;


/////

assign rf_raddr1 = rs;
assign rf_raddr2 = ds_valid && need_rs2 ? rt : rxn;
assign xn_value  = rf_rdata2;

regfile u_regfile(
    .clk    (clk      ),
    .raddr1 (rf_raddr1),
    .rdata1 (rf_rdata1),
    .raddr2 (rf_raddr2),
    .rdata2 (rf_rdata2),
    .we     (rf_we    ),
    .waddr  (rf_waddr ),
    .wdata  (rf_wdata ),
    .x1_value   (x1_value),
    .regs_o (regs_o)
    );


assign {    
            ms_valid, 
            ms_gr_we ,
            ms_dest,
            ms_fw_data
                } = ms_to_ds_bus ;
assign  {
            es_load_op,//42:42
            es_valid,//41:41  
            es_gr_we  ,//~es_inst_lw,//40:37
            es_dest,         //32:36
            es_fw_data    //31:0
                } = es_to_ds_bus  ;
assign  {
            ws_valid, 
             ws_gr_we,
             ws_dest,
             ws_fw_data
                } = ws_to_ds_bus ;


//rs forward
assign rs_value =    es_valid  && es_gr_we && rs == es_dest && rs != 5'h00 ? es_fw_data:
                     ms_valid  && ms_gr_we && rs == ms_dest && rs != 5'h00 ? ms_fw_data:
                     ws_valid  && ws_gr_we && rs == ws_dest && rs != 5'h00 ? ws_fw_data:
                                                               rf_rdata1;
                            

                            
//rt forward
assign rt_value =    es_valid && es_gr_we && rt == es_dest && rt != 5'h00 ? es_fw_data:
                     ms_valid && ms_gr_we && rt == ms_dest && rt != 5'h00 ? ms_fw_data:
                     ws_valid && ws_gr_we && rt == ws_dest && rt != 5'h00 ? ws_fw_data:
                                                             rf_rdata2;
                  
                  
wire rs1_g_rs2;
wire rs2_g_rs1;
wire [64:0] rs_u;
wire [64:0] rt_u;
wire [64:0] rs_s;
wire [64:0] rt_s;
wire [64:0] rs_v;
wire [64:0] rt_v;
wire  rs1_l_rs2;

assign rs_u = {1'b0,rs_value};
assign rt_u = {1'b0,rt_value};
assign rs_s = {rs_value[63],rs_value};
assign rt_s = {rt_value[63],rt_value};
assign rs_v = inst_bgeu|| inst_bltu ? rs_u : rs_s;
assign rt_v = inst_bgeu|| inst_bltu ? rt_u : rt_s; 

assign rs1_g_rs2 = $signed(rs_v)  >  $signed(rt_v);
assign rs2_g_rs1 = ~rs1_g_rs2 && ~rs_eq_rt;

assign rs1_l_rs2 = ~rs1_g_rs2 & ~rs_eq_rt;
assign rs_eq_rt = (rs_value == rt_value);
//bge 大于或者等于才跳转
//blt 小于才跳转
//assign rs_eq_0 = (rs_value == 32'b0);
//计算机中数据以补码的形式存入,0表示正数�?1表示负数
// assign rs_g_0 =  ~rs_value[31:31] ;
assign br_taken = (   inst_beq    && rs_eq_rt
                   || inst_bne    && !rs_eq_rt
                   || inst_blt    && rs1_l_rs2
                   || inst_bltu   && rs1_l_rs2
                   || inst_bge    && !rs1_l_rs2
                   || inst_bgeu   && !rs1_l_rs2
                   || inst_jalr
                   || inst_jal

) && ds_valid ;
// wire  [63:0] nop_pc;
// assign          nop_pc = ds_pc + 3'h4;
// wire [63:0] add_result;

assign add_src1 = inst_jalr ? rs_value :  ds_pc;
//assign add_src2 = (inst_beq || inst_bne || inst_blt || inst_bltu || inst_bge || inst_bgeu || inst_jal || inst_jalr) ? {{32{imm[31]}},imm} : 4;
assign add_src2 = br_taken ? {{32{imm[31]}},imm} : 4;
assign br_target = add_src1 + add_src2;

// assign  = add_result;
endmodule
